package edu.study.common.util.bean;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;

/**
 * @author yeahwell
 */
public class ObjectConvertUtil {

	private static final Logger logger = LoggerFactory.getLogger(ObjectConvertUtil.class);

	// 定义jackson对象
	private static final ObjectMapper MAPPER = new ObjectMapper();

	/**
	 * 对象转换成map
	 *
	 * @param object
	 * @param marks
	 *            true 更新所有 false null不更新
	 * @return Map<String, Object>
	 */
	public static Map<String, Object> objectToMap(Object object, boolean marks) {
		try {
			if (object instanceof Map) {
				return (Map)object;
			}
			Map<String, Object> returnMap = BeanUtils.describe(object);
			returnMap.remove("class");
			return returnMap;
		} catch (Exception e) {
			logger.error("objectToMap error", e);
		}
		return new HashMap<>();
//		Map<String, Object> map = new HashMap<String, Object>();
//		Field[] Fields = object.getClass().getDeclaredFields();// 获取本类所有属性公有私有都能获取。但是不能获取继承的。
//		for (Field field : Fields) {
//			String fieldName = field.getName();
//			try {
//				PropertyDescriptor pd = new PropertyDescriptor(fieldName, object.getClass());
//				Method fieldGetMet = pd.getReadMethod();// 获得读方法
//				String key = pd.getDisplayName();
//				Object value = fieldGetMet.invoke(object);
//				if (value != null && !"".equals(value)) {
//					map.put(key, value);
//				} else if (marks) {
//					map.put(key, "");
//				}
//			} catch (Exception e) {
//				logger.error("objectToMap error", e);
//			}
//		}
//		return map;

		//反射对象为map，包含父类对象
//		Map<String,Object> reMap = new HashMap<String,Object>();
//		if (object == null) {
//			return null;
//		}
//		try {
//			Class<?> objClass = object.getClass();
//			while(objClass != null){
//				Field[] fields = objClass.getDeclaredFields();
//				for(int i=0;i<fields.length;i++){
//					try {
//						Field f = objClass.getDeclaredField(fields[i].getName());
//						f.setAccessible(true);
//						Object o = f.get(object);
//						reMap.put(fields[i].getName(), o);
//					} catch (Exception e) {
//						logger.error("objectToMap error", e);
//					}
//				}
//				objClass = objClass.getSuperclass();
//			}
//		} catch (Exception e) {
//			logger.error("objectToMap error", e);
//		}
//		return reMap;
	}

	/**
	 * model转换成map
	 *
	 * @param object
	 * @return Map<String, Object>
	 */
	public static Map<String, Object> objectToMapAll(Object object) {
		return ObjectConvertUtil.objectToMap(object, true);
	}

	/**
	 * model转换成map
	 *
	 * @param object
	 * @return Map<String, Object>
	 */
	public static Map<String, Object> objectToMapNotNull(Object object) {
		return ObjectConvertUtil.objectToMap(object, false);
	}

	/**
	 * 利用反射填充对象
	 *
	 * @param object
	 * @param field
	 * @param value
	 * @return
	 */
	public static Object mapToObject(Object object, Map<String, Object> resultMap) {
		return mapToObject(object, resultMap, "");
	}

	/**
	 * 排除个别的KEY值
	 *
	 * @param object
	 * @param resultMap
	 * @param args
	 * @return
	 */
	public static Object mapToObject(Object object, Map<String, Object> resultMap, String... args) {
		try {
			Iterator<String> keys = resultMap.keySet().iterator();
			while (keys.hasNext()) {
				String field = keys.next();
				Object value = resultMap.get(field);

				boolean contains = true;
				for (int i = 0; args.length != 0 && i < args.length; i++) {
					if (field.equals(args[i].toUpperCase())) {
						contains = false;
						break;
					}
				}
				if (value != null && contains) {
					String methodName = "set" + Character.toUpperCase(field.charAt(0))
							+ field.toLowerCase().substring(1);
					Class<?> paramTypeClass = value.getClass();
					if (value instanceof java.sql.Timestamp) {
						paramTypeClass = Date.class;
					}
					Method method = object.getClass().getMethod(methodName, paramTypeClass);
					if (method != null) {
						method.invoke(object, value);
					}
				}
			}
		} catch (Exception ex) {
			logger.error("mapToObject error", ex);
		}
		return object;
	}

	public static String map2Json(Map<String, Object> value) {
		if (value == null || value.isEmpty()) {
			return "{}";
		}
		try {
			GsonBuilder gb = new GsonBuilder();
			Gson g = gb.create();
			return g.toJson(value, new TypeToken<Map<String, Object>>() {
			}.getType());
		} catch (Exception e) {
			logger.error("map2Json error", e);
			return "{}";
		}
	}

	public static String mapString2Json(Map<String, String> value) {
		if (value == null || value.isEmpty()) {
			return "{}";
		}
		try {
			GsonBuilder gb = new GsonBuilder();
			Gson g = gb.create();
			return g.toJson(value, new TypeToken<Map<String, String>>() {
			}.getType());
		} catch (Exception e) {
			logger.error("map2Json error", e);
			return "{}";
		}
	}

	public static String objectToJson(Object o) {
		String targetStr = "";
		try {
			targetStr = new GsonBuilder()
					.create().toJson(o);
		} catch (Exception e) {
			logger.error("log输出发生错误：", e);
		}
		return targetStr;
	}

	/**
	 * 拼装json串
	 *
	 * @param str1
	 * @param str2
	 * @return
	 */
	public static String joinJsonStrings(String str1, String str2) {
		String result = "";
		if (StringUtils.isEmpty(str1) && StringUtils.isEmpty(str2)){
			return "{}";
		}
		if (StringUtils.isEmpty(str1)) {
			return str2;
		}
		if (StringUtils.isEmpty(str2)) {
			return str1;
		}
		Map<String, Object> map1 = json2MapG(str1);
		Map<String, Object> map2 = json2MapG(str2);
		for (String str : map2.keySet()) {
			map1.put(str, map2.get(str));
		}
		result = map2Json(map1);
		return result;
	}

	public static Map<String, Object> json2MapG(String str) {
		if (StringUtils.isEmpty(str)) {
			return new HashMap<String, Object>(0, 1F);
		}
		try {
			GsonBuilder gb = new GsonBuilder();
			Gson g = gb.create();
			Map<String, Object> map = g.fromJson(str, new TypeToken<Map<String, Object>>() {
			}.getType());
			return map;
		} catch (Exception e) {
			logger.error("json2MapG error:", e);
			return new HashMap<String, Object>(0, 1F);
		}
	}

	public static Map<String, String> json2MapString(String str) {
		if (StringUtils.isEmpty(str)) {
			return new HashMap<String, String>(0, 1F);
		}
		try {
			GsonBuilder gb = new GsonBuilder();
			Gson g = gb.create();
			Map<String, String> map = g.fromJson(str, new TypeToken<Map<String, String>>() {
			}.getType());
			return map;
		} catch (Exception e) {
			logger.error("json2MapString error:", e);
			return new HashMap<String, String>(0, 1F);
		}
	}

	/**
	 * json转换成model
	 *
	 * @return
	 */
	public static <T> T json2Object(String str, Class<T> beanType) {
		try {
			Gson g = new GsonBuilder()
					.create();
			return g.fromJson(str, beanType);
		} catch (Exception e) {
			logger.error("json2Object error", e);
			return null;
		}
	}

	/**
	 * json转换成List
	 *
	 * @param beanType
	 * @return
	 */
	public static <T> List<T> jsonToList(String str, Class<T> beanType) {
		JavaType javaType = MAPPER.getTypeFactory().constructParametricType(List.class, beanType);
		try {
			List<T> list = MAPPER.readValue(str, javaType);
			return list;
		} catch (Exception e) {
			logger.error("ObjectConvertUtil.jsonToList();发生异常 ", e);
		}

		return null;
	}

}
